package uitl

import (
	"Projects/CavaCloudSys/cavasmusrc/internal/common"
	"bytes"
	"context"
	"crypto/sha256"
	"database/sql/driver"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
	"time"

	"github.com/pkg/errors"
	qflog "github.com/qf-tech/qftech-base/pkg/log"
)

func CalculateHash(toBeHashed string) string {
	hashInBytes := sha256.Sum256([]byte(toBeHashed))
	hashStr := hex.EncodeToString(hashInBytes[:])
	return hashStr
}

func GenWsse(username string, password string, nonce string) string {
	created := time.Now().Format("2006-01-02T15:04:05Z")
	plainData := fmt.Sprintf("%s%s%s%s", username, password, nonce, created)
	digest := CalculateHash(plainData)

	wsseInfo := fmt.Sprintf("UsernameToken Username=\"%s\", PasswordDigest=\"%s\", Nonce=\"%s\", Created=\"%s\"",
		username, digest, nonce, created)
	return wsseInfo
}

func HttpPostJson(ctx context.Context, url string, reqBody interface{}, headers map[string]string, timeout time.Duration) (interface{}, error) {
	log := qflog.GetLogger().GetCtx(ctx).Sugar()
	c := &http.Client{Timeout: timeout}

	bytesData, err := json.Marshal(reqBody)
	if err != nil {
		return nil, errors.Wrap(err, "req body marshal err")
	}
	reader := bytes.NewReader(bytesData)
	req, err := http.NewRequest("POST", url, reader)
	if err != nil {
		return nil, err
	}

	for k, v := range headers {
		req.Header.Add(k, v)
	}

	log.Infof("send post request, url: %s, header: %v, body: %s", url, headers, string(bytesData))
	resp, err := c.Do(req)
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	log.Infof("receive post response, code: %d, body: %s", resp.StatusCode, string(body))

	var v interface{}
	err = json.Unmarshal(body, &v)
	if err != nil {
		return nil, err
	}

	return v, nil
}

type LocalTime time.Time

func (t LocalTime) Value() (driver.Value, error) {
	var zeroTime time.Time
	tlt := time.Time(t)
	if tlt.UnixNano() == zeroTime.UnixNano() {
		return nil, nil
	}
	return tlt, nil
}

func (t *LocalTime) Scan(v interface{}) error {
	if value, ok := v.(time.Time); ok {
		*t = LocalTime(value)
		return nil
	}
	return fmt.Errorf("can not convert %v to timestamp", v)
}

func (t *LocalTime) String() string {
	// 如果时间 null 那么我们需要把返回的值进行修改
	if t == nil || t.IsZero() {
		return ""
	}
	return fmt.Sprintf("%s", time.Time(*t).Format(common.TimeFormatCMT))
}

func (t *LocalTime) IsZero() bool {
	return time.Time(*t).IsZero()
}

func (t *LocalTime) UnmarshalJSON(data []byte) error {
	if string(data) == "null" {
		return nil
	}
	var err error
	//前端接收的时间字符串
	str := string(data)
	//去除接收的str收尾多余的"
	timeStr := strings.Trim(str, "\"")
	t1, err := time.ParseInLocation(common.TimeFormatCMT, timeStr, time.Local)
	*t = LocalTime(t1)
	return err
}

func (t LocalTime) MarshalJSON() ([]byte, error) {
	tTime := time.Time(t)
	// 如果时间值是空或者0值 返回为null 如果写空字符串会报错
	if &t == nil || t.IsZero() {
		return []byte("null"), nil
	}
	return []byte(fmt.Sprintf("\"%s\"", tTime.Format(common.TimeFormatCMT))), nil
}
